package com.example.threadstack;

import org.apache.commons.lang3.concurrent.BasicThreadFactory;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.data.redis.core.RedisCallback;
import org.springframework.data.redis.core.StringRedisTemplate;
import org.springframework.web.bind.annotation.PathVariable;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RestController;
import org.springframework.web.context.request.async.DeferredResult;

import java.util.concurrent.CompletableFuture;
import java.util.concurrent.ExecutorService;
import java.util.concurrent.Executors;

import static com.example.threadstack.Utils.getCurrentTime;
import static com.example.threadstack.Utils.sleepForMs;


@RestController
@RequestMapping("low-resource")
public class LowResourceController {
    private ExecutorService executorService = Executors.newCachedThreadPool(new BasicThreadFactory
            .Builder()
            .namingPattern("Low-Resource-%d")
            .build()
    );

    @Autowired
    private StringRedisTemplate redisTemplate;

    @RequestMapping("/{batch}")
    public DeferredResult<String> lowReource(@PathVariable int batch){
        DeferredResult<String> result = new DeferredResult<>(10 * 1000L, "TimeOut");
        CompletableFuture<String>[] futures = new CompletableFuture[batch];
        for (int i=0;i<batch;i++){
            futures[i] = CompletableFuture.supplyAsync(this::getValue, executorService);
        }
        CompletableFuture.allOf(futures).thenRun( ()-> result.setResult("SUCCESS"));
        return result;
    }

    private String getValue() {
        try {
            return redisTemplate.execute((RedisCallback<String>)(redisConnection -> {
                sleepForMs(5000);
                return getCurrentTime() + redisConnection;
            }));
        }catch (Exception e){
            e.printStackTrace();
        }
        return "ERROR";

    }
}
